package ar.edu.itba.it.poo

import scala.collection.mutable.HashMap

trait Bag[T] {
	def add(element: T)
	def count(element: T): Int
	def size: Int
	def sizeDistinct: Int
	def contains(element: T): Boolean
	def remove(element: T)
}

class HashBag[T] extends Bag[T] {
	
	private var elements = HashMap[T, Int]()
	
	def add(element: T) { elements(element) = elements.getOrElse(element, 0) + 1 }
	def count(element: T): Int = elements.getOrElse(element, 0)
	def size: Int = elements.values.sum
	def sizeDistinct: Int = elements.size
	def contains(element: T): Boolean = elements.contains(element)
	def remove(element: T) { 
		val data = elements.get(element)
		if (!data.isDefined) {
			throw new NoSuchElementException()
		} else {
			if (data.get == 1) elements.remove(element) else elements(element) = data.get - 1 
		}
	}
}

object BagTest extends Application {
	val bag = new HashBag[String]()
	
    bag.add("Hola"); 
    bag.add("Hola"); 
    println(bag.count("Hola"));   //Imprime 2
    
    bag.add("Chau"); 
    println(bag.size);    //Imprime 3 
    println(bag.sizeDistinct);   //Imprime 2 
    println(bag.contains("Chau"));  //Imprime true
    
    bag.remove("Hola"); 
    println(bag.count("Hola"));   //Imprime 1
    
    bag.remove("Hola"); 
    println(bag.contains("Hola"));  //Imprime false
    
    try {
    	bag.remove("Hola");     //Lanza NoSuchElementException
    } catch {
    	case e: NoSuchElementException => println("NoSuchElementException")
    }
}